package com.miaopasi.securitydemo.config.security.filter;

import cn.hutool.core.lang.Console;
import cn.hutool.core.util.StrUtil;
import com.miaopasi.securitydemo.config.security.ValidateCodeException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Objects;

/***
 * 验证码过滤器
 * @author lixin
 */
@Component("validateCodeFilter")
public class ValidateCodeFilter extends OncePerRequestFilter implements Filter {
    private final AuthenticationFailureHandler authenticationFailureHandler;

    @Autowired
    public ValidateCodeFilter(AuthenticationFailureHandler authenticationFailureHandler) {
        this.authenticationFailureHandler = authenticationFailureHandler;
    }

    @Override
    protected void doFilterInternal(
            HttpServletRequest request,
            HttpServletResponse response,
            FilterChain filterChain
    ) throws ServletException, IOException {
        // 必须是登录的post请求才能进行验证，其他的直接放行
        if (StrUtil.equals("/doLogin", request.getRequestURI()) && StrUtil.equalsIgnoreCase(request.getMethod(), "post")) {
            Console.log("进入[自定义验证码过滤器]");
            try {
                // 1. 进行验证码的校验
                validate(request);
            } catch (AuthenticationException e) {
                // 2. 捕获步骤1中校验出现异常，交给失败处理类进行进行处理
                authenticationFailureHandler.onAuthenticationFailure(request, response, e);
                return;
            }
        }
        // 校验通过，就放行
        filterChain.doFilter(request, response);
    }

    /**
     * 验证输入的验证码是否正确
     *
     * @param request 请求对象
     */
    private void validate(HttpServletRequest request) throws ServletRequestBindingException {
        String code1 = ServletRequestUtils.getStringParameter(request, "code");
        Object code2 = request.getSession().getAttribute("code");
        // 移除保存的验证码，防止重复使用验证码进行登录
        request.getSession().removeAttribute("code");
        Console.log("输入的验证码为：{}，Session中的code为：{}", code1, code2);
        if (Objects.isNull(code1) || Objects.isNull(code2) || !Objects.equals(code1, code2)) {
            throw new ValidateCodeException();
        }
    }
}
